'/
' arraylist - version 1.05
' Written 2010 by Anton Berlin.
' 
' =========================================================================
' 
' This program is free software; you can redistribute it and/or modify
' it under the terms of the GNU Lesser General Public License as published
' by the Free Software Foundation; either version 3 of the License.
' 
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.
' 
' You should have received a copy of the GNU Lesser General Public License
' along with this program; if not, write to the Free Software
' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'/

superstrict

import BRL.Reflection

type ArrayList

	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method first:object()
	
		if (not isEmpty()) ..
			return m_content[1];
		
		return null;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method last:object()
	
		if (not isEmpty()) ..
			return m_content[m_content.length-1];
		
		return null;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method getElement:object(element:int)
	
		if (element < 0) ..
			runtimeError("Out of bounds.");
		
		if (not isEmpty()) ..
			return m_content[element+1];
		
		return null;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method setElement(element:int, obj:object)
	
		if (element < 0) ..
			runtimeError("Out of bounds.");
		
		if (not isEmpty()) ..
			m_content[element+1] = obj;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method moveElementDown(element:int)
	
		local item1:object = getElement(element);
		local item2:object = getElement(element+1);
		
		if (count() <= 1 or last() = item1) ..
			return;
		
		setElement(element, item2);
		setElement(element+1, item1);
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method moveElementUp(element:int)
	
		local item1:object = getElement(element);
		local item2:object = getElement(element-1);
		
		if (count() <= 1 or first() = item1) ..
			return;
		
		setElement(element, item2);
		setElement(element-1, item1);
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method contains:byte(obj:object)
	
		if (not isEmpty()) then
		
			for local item:object = eachin m_content
			
				if (obj = item) ..
					return true;
			
			next
		
		end if
		
		return false;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method addLast(obj:object)
	
		m_content = m_content[..m_content.length+1];
		m_content[m_content.length-1] = obj;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method removeElement:object(element:int)
	
		if (count() = 0) ..
			return null;
		
		element :+ 1; '// Compensate for the empty element in the beginning.
		
		if (element > m_content.length-1) ..
			return null;
		
		local removedItem:object;
		
		if (count() = 1) then
		
			if (element = 1) ..
				removedItem = removeLast();
			
			return removedItem;
		
		end if
		
		local index:int = 0;
		local removing:byte = false;
		local length:int = count();
		
		while (index < length)
		
			index :+ 1;
			
			if (index = element) then
			
				removing = true;
				removedItem = m_content[index];
			
			end if
			
			if (removing and index < length) ..
				m_content[index] = m_content[index+1];
			
			if (index = length-1) then
			
				removeLast();
				exit;
			
			end if
		
		end while
		
		return removedItem;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method remove:object(item:object)
	
		if (count() = 0) ..
			return null;
		
		local removedItem:object;
		
		if (count() = 1) then
		
			if (getElement(0) = item) ..
				removedItem = removeLast();
			
			return removedItem;
		
		end if
		
		local index:int = 0;
		local removing:byte = false;
		local length:int = count();
		
		while (index < length)
		
			index :+ 1;
			
			if (m_content[index] = item) then
			
				removing = true;
				removedItem = m_content[index];
			
			end if
			
			if (removing and index < length) ..
				m_content[index] = m_content[index+1];
			
			if (index = length-1) then
			
				removeLast();
				exit;
			
			end if
		
		end while
		
		return removedItem;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method removeLast:object()
	
		local removedItem:object = m_content[m_content.length-1];
		m_content = m_content[..m_content.length-1];
		return removedItem;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method count:int()
	
		if (m_content) ..
			return m_content.length - 1;
		
		return 0;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method clear()
	
		m_content = m_content[..1];
		m_content[0] = null;
	
	end method
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	function clone:ArrayList(existingList:ArrayList)
	
		local list:ArrayList = new ArrayList;
		list.m_content = existingList.m_content[..];
		return list;
	
	end function
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		
	'// -----------------------------------------------------------------------------------------------------------------
	method isEmpty:byte()
	
		if (not m_content) ..
			return true;
		
		if (m_content.length <= 1) ..
			return true;
		
		return false;
	
	end method
	
	field m_content:object[1];

end type
